{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "87f92d8b",
   "metadata": {},
   "source": [
    "## 2.2 微积分相关知识"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "269333f4",
   "metadata": {},
   "source": [
    "早在公元前7世纪，古希腊科学家、哲学家泰勒斯就对球的面积、体积、与长度等问题的研究就含有微积分思想。公元前3世纪，古希腊数学家、力学家阿基米德的著作《圆的测量》和《论球与圆柱》中就已含有积分学的萌芽。\n",
    "\n",
    "到了17世纪，英国数学家牛顿和德国数学家莱布尼茨分别发明了微积分的基本概念和运算法则。牛顿提出了微积分的概念，并用它来解决许多物理问题。莱布尼茨则发明了微积分的符号，并用它来研究微积分的基本性质。经过他们的工作，微积分不再是古希腊几何的附庸和延展，而是一门独立的学科。\n",
    "\n",
    "微积分在近代又发展出了许多新的概念和方法，已经成为数学中的一个重要分支，主要研究连续函数、曲线和曲面的性质以及它们的应用。这些概念和方法的发展使得微积分在数学和物理学中得到了广泛的应用，并在统计学、工程学、经济学等领域也有所发挥。\n",
    "\n",
    "微积分的发展同样促进了计算机科学的发展，它与深度学习之间有着密切的关系，例如著名的梯度下降算法就是基于微积分的概念发展出来的，微积分的一些概念和方法在深度学习中有着广泛的应用。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7c84d1f9",
   "metadata": {},
   "source": [
    "### 2.2.1 极限"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "222346a6",
   "metadata": {},
   "source": [
    "在微积分中，极限是一个重要的基础概念。极限表示在某一点处函数值趋近于某一特定值的过程。\n",
    "\n",
    "极限的一般写法为：\n",
    "\n",
    "$$\\lim_{x \\to a}f(x)=L$$\n",
    "\n",
    "其中，a 是极限的点，L 是函数在 a 处的极限值。当函数在 x 趋近于 a 的过程中，函数的值趋近于 L，则称函数在 a 处的极限值为 L。\n",
    "\n",
    "通俗理解，函数f(x)中的变量x，x在变大（或者变小）的变化过程中，逐渐向某一个确定的数值a不断地逼近而永远不能够重合到a的过程中，此变量的变化，被人为规定为永远靠近而不停止，或者说不断靠近a的趋势。**可以将极限理解为一种变化状态的描述。**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f0107316",
   "metadata": {},
   "source": [
    "### 2.2.2 导数"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "69a80223",
   "metadata": {},
   "source": [
    "导数是微积分学中重要的基础概念，**简单来讲就是指一个函数在某一点处的变化率。**\n",
    "\n",
    "在数学中，我们通常用符号 $f'(x)$ 来表示函数 $y=f(x)$ 的导数，也可以记为 $\\frac{\\mathrm{d} f(x)}{\\mathrm{d} x} $ 。例如，设函数 $y=f(x)=\\frac{x^3-3x^2+6}{2} $ 的图像如下：\n",
    "\n",
    "<img src=\"./images/2-2-1.png\" width=\"30%\" ></img>\n",
    "\n",
    "在图中，我们可以看到函数 $y=f(x)$ 在 $x=2$ 处有一个拐点，这个拐点的斜率就是函数在 $x=2$ 处的导数。我们可以使用导数的公式来计算函数在 $x=2$ 处的导数，即：\n",
    "\n",
    "$$f'(2)=\\lim_{h \\to 0}\\frac{f(2+h)-f(2)}{h}$$\n",
    "\n",
    "在上面的公式中，$h$ 是一个趋近于 0 的数，当 $h$ 趋近于 0 时，函数值 $f(2+h)$ 就趋近于函数值 $f(2)$。导数的值就是这两个函数值的变化率。即如下图所示：\n",
    "\n",
    "<img src=\"./images/2-2-2.png\" width=\"30%\" ></img>\n",
    "\n",
    "下面用代码实现验证一下。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "42fa2279",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "h值: 1.0000000, 极限值: 2.0000000\n",
      "h值: 0.1000000, 极限值: 0.1550000\n",
      "h值: 0.0100000, 极限值: 0.0150500\n",
      "h值: 0.0010000, 极限值: 0.0015005\n",
      "h值: 0.0001000, 极限值: 0.0001500\n",
      "h值: 0.0000100, 极限值: 0.0000150\n",
      "h值: 0.0000010, 极限值: 0.0000015\n",
      "h值: 0.0000001, 极限值: 0.0000002\n"
     ]
    }
   ],
   "source": [
    "def f(x):\n",
    "    return (x ** 3 - 3 * (x ** 2) + 6) / 2\n",
    "\n",
    "for i in range(8):\n",
    "    h = 0.1 ** i\n",
    "    print(\"h值: {:.7f}, 极限值: {:.7f}\".format(h, (f(2 + h) - f(2)) / h))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d0b1326c",
   "metadata": {},
   "source": [
    "通过上面的例子可以看出，随着 $h$ 越来越趋近于0，极限值就越来越接近其真实的导数值。\n",
    "\n",
    "对于导数的实际意义，假设上图是一段时间内某人跑步速度的曲线，那么导数表示的就是某个时刻的变化率，也就是加速度。\n",
    "\n",
    "以下是几种常见函数的导数计算方法（其中 $C$ 是一个常数）：\n",
    "\n",
    "* 常数函数 $f(x) = C$ 有 $f'(x) = 0$\n",
    "* 幂函数  $f(x) = x^n$ 有 $f'(x) = nx^{n-1}$\n",
    "* 指数函数 $f(x) = e^x$ 有 $f'(x) = e^x$\n",
    "* 对数函数 $f(x) = ln(x)$ 有 $f'(x) = \\frac{1}{x}$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "60155f77",
   "metadata": {},
   "source": [
    "### 2.2.3 微分"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "70a07eee",
   "metadata": {},
   "source": [
    "微分是指对函数的局部变化的一种线性描述。微分可以近似地描述当函数自变量的取值作足够小的改变时，函数的值是怎样改变的。\n",
    "\n",
    "看上去微分和导数很相似，实际上微分和导数是两个不同的概念。但对一元函数来说，可微与可导是等价的概念。\n",
    "\n",
    "对于函数 $y=f(x)$ 来说，一般把自变量的微分记作 $\\mathrm{d} x$ 。如果 $f(x)$ 可微，其微分等于导数乘以自变量的微分 $\\mathrm{d} x$ ，即函数 $y=f(x)$ 的微分可记作 $\\mathrm{d} y = \\mathrm{d} f(x) = f'(x) \\mathrm{d} x$ 。\n",
    "\n",
    "**这两个概念有些绕，同学们只要简单理解下面两句话即可。**\n",
    "\n",
    "* **导数 表示 变化率**\n",
    "* **微分 表示 变化量**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e3a5400e",
   "metadata": {},
   "source": [
    "### 2.2.4 偏导数"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b9ab83fb",
   "metadata": {},
   "source": [
    "前面讨论的都是只包含一个变量的函数，那么当扩展到多元函数时，就有了偏导数的概念。**偏导数指的是多元函数在某一点处关于某一变量的导数。**\n",
    "\n",
    "在数学中，通常用符号 $\\frac{\\partial f(x,y)}{\\partial x}$ 来表示多元函数 $z=f(x,y)$ 关于 $x$ 的偏导数，即：\n",
    "\n",
    "$$\\frac{\\partial f(x,y)}{\\partial x}=\\lim_{h \\to 0}\\frac{f(x+h,y)-f(x,y)}{h}$$\n",
    "\n",
    "同理，也可以用符号 $\\frac{\\partial f(x,y)}{\\partial y}$ 来表示多元函数 $z=f(x,y)$ 关于 $y$ 的偏导数，即：\n",
    "\n",
    "$$\\frac{\\partial f(x,y)}{\\partial y}=\\lim_{h \\to 0}\\frac{f(x,y+h)-f(x,y)}{h}$$\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "269d41e0",
   "metadata": {},
   "source": [
    "### 2.2.5 梯度"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "52b6e1cb",
   "metadata": {},
   "source": [
    "**梯度其实就是一个包含所有偏导数的向量**，表示某一函数在该点处的方向导数沿着该方向取得最大值，即函数在该点处沿着该方向变化最快，变化率最大。\n",
    "\n",
    "在数学中，我们通常用 $\\nabla f(x,y)$ 来表示多元函数 $z=f(x,y)$ 的梯度，其中，$\\nabla f(x,y)$ 是一个向量，它的每一个分量分别对应着函数关于 $x$ 和 $y$ 的偏导数。\n",
    "\n",
    "例如，设函数 $z=f(x,y)=x^2+y^2$，那么该函数的梯度向量就是：\n",
    "\n",
    "$$\\nabla f(x,y)=\\begin{pmatrix} 2x , 2y \\end{pmatrix}$$\n",
    "\n",
    "在深度学习中，我们常常使用梯度下降算法来训练模型，而梯度下降算法就是利用梯度向量的信息来更新模型参数的。\n",
    "\n",
    "具体来说，就是使用如下的公式来更新模型参数：\n",
    "\n",
    "$$\\theta_{t+1}=\\theta_t-\\eta \\nabla_{\\theta} J(\\theta_t)$$\n",
    "\n",
    "在上面的公式中，$\\theta_t$ 表示模型参数在第 $t$ 次迭代时的值，$\\theta_{t+1}$ 表示模型参数在第 $t+1$ 次迭代时的值，$\\eta$ 表示学习率，$\\nabla_{\\theta} J(\\theta_t)$ 表示损失函数 $J(\\theta)$ 关于模型参数 $\\theta$ 的梯度。\n",
    "\n",
    "通过不断迭代更新模型参数，就可以使用梯度下降算法来训练模型了。这部分在后面的章节还会具体讲解，同学们了解即可。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "101bc163",
   "metadata": {},
   "source": [
    "### 2.2.6 链式法则"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1696800d",
   "metadata": {},
   "source": [
    "在深度学习中面对的函数往往是复合函数，所以很难直接计算梯度，这就需要链式法则出马。\n",
    "\n",
    "微积分中的链式法则是用来计算复合函数导数的方法。具体来说，在计算复合函数的导数时，可能会用到多个函数，而每个函数都有自己的导数表达式。如果想要计算复合函数的导数，就需要将所有的导数表达式组合起来。这时，就可以使用链式法则来解决这个问题。\n",
    "\n",
    "设 $x$ 是实数，函数 $f$ 和 $g$ 都是可微的。假设 $y = g(x)$ 且 $z = f(g(x)) = f(y)$ 。那么链式法则公式如下：\n",
    "\n",
    "$$ \\frac{\\mathrm{d} z}{\\mathrm{d} x} = \\frac{\\mathrm{d} z}{\\mathrm{d} y} \\cdot \\frac{\\mathrm{d} y}{\\mathrm{d} x} $$\n",
    "\n",
    "**实际上这是一个非常简单的性质，就是一层一层增加可以“相互抵消”的分子分母。**\n",
    "\n",
    "下面举个例子，假设我们有两个函数 $f(x)=x^2$ 和 $g(x)=x+1$，我们要计算出 $h(x)=f(g(x))=(x+1)^2$ 的导数。根据链式法则，我们可以得到：\n",
    "\n",
    "$$h'(x)=f'(g(x))\\cdot g'(x)=2(x+1)\\cdot 1=2x+2$$\n",
    "\n",
    "所以，$h(x)=x^2+2x+1$ 的导数为 $2x+2$。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "07dc307f",
   "metadata": {},
   "source": [
    "[Next 2-3 概率](./2-3%20%E6%A6%82%E7%8E%87.ipynb)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0bfc1cb3",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
